#include "TcpServer.hpp"
#include "Protocol.hpp"
#include "Daemon.hpp"
#include "MyPthread/Log.hpp"

#include <memory>
using namespace LogModule;

using cal_fun = std::function<Response(const Request &req)>;
class Calculator
{
public:
    Response operator()(const Request &req)
    {
        Response resp;
        int x = req.GetX(), y = req.GetY();
        char oper = req.GetOper();
        switch (oper)
        {

        case '+':
            resp.SetRes(x + y);
            break;
        case '-':
            resp.SetRes(x - y);
            break;
        case '*':
            resp.SetRes(x * y);
            break;
        case '/':
            if (y == 0)
            {
                resp.SetCode(1); // 1 就是除数为0
            }
            else
            {
                /* code */
                resp.SetRes(x / y);
            }
            break;
        case '%':
        {
            if (y == 0)
            {
                resp.SetCode(2); // 2 就是mod 0
            }
            else
            {
                resp.SetRes(x % y);
            }
        }
        break;
        default:
            resp.SetCode(3); // 3 用户发来的计算类型，无法识别
            break;
        }
        return resp;
    }
};

// package一定会有完整的报文吗？？不一定把
// 不完整->继续读
// 完整-> 提取 -> 反序列化 -> Request -> 计算模块，进行处理
class Parse
{
public:
    Parse(cal_fun c)
        : _cal(c)
    {
    }
    std::string Entry(std::string &package)
    {
        // 1. 判断报文的完整性！
        std::string content;
        std::string resp_str;
        LOG(LogLevel::DEBUG) << "package: \n"
                             << package;

        // 可能有多条完整报文，所以需要循环处理
        while (Decode(package, &content))
        {
            if (content.empty())
            {
                std::cerr << "incomplate content" << std::endl;
                break;
            }
            // 2. 反序列化， content是一个曾经被序列化的request
            Request req;
            req.Deserialize(content);

            // 3. 计算
            Response resp = _cal(req);

            LOG(LogLevel::INFO) << "Content:\n";
            std::cout << "#############" << std::endl;
            req.Print();
            std::cout << "#############" << std::endl;

            // 4. 序列化
            std::string res_content;
            resp.Serialize(res_content);
            LOG(LogLevel::INFO) << "res_content: \n"
                                << res_content;

            // 5. 添加长度报头字段！
            Encode(res_content);
            LOG(LogLevel::INFO) << "res_content: \n"
                                << res_content;

            // 6. 拼接应答
            resp_str += res_content;
        }
        LOG(LogLevel::DEBUG) << "respstr: \n"
                             << resp_str;
        return resp_str;
    }

private:
    cal_fun _cal;
};

int main(int argc, char *argv[])
{
    // ENABLE_CONSOLE_LOG();
    ENABLE_FILE_LOG();
    
    if (argc != 2)
    {
        std::cerr << "Usage: " << argv[0] << " localport" << std::endl;
        Die(USAGE_ERR);
    }
    // std::string ip = argv[1];
    uint16_t port = std::stoi(argv[1]);

    // 0.创建守护进程
    Daemon(false, false);

    // 1. 计算器模块(应用层)
    Calculator cal;
    // 2. 解析模块（表示层）
    std::shared_ptr<Parse> parse = std::make_shared<Parse>(cal);
    // 3. 服务器模块（传输层）
    std::shared_ptr<TcpServer> server = std::make_shared<TcpServer>(std::stoi(argv[1]));

    server->InitServer();
    server->RegisterSerive(
        [&parse](std::string &package)
        {
            return parse->Entry(package);
        });

    server->Start();

    return 0;
}